// HTTP API 服务
import axios, { type AxiosInstance, type AxiosRequestConfig, type AxiosError } from 'axios'
import { config } from '@/config'
import { userStorage } from '@/utils/storage'
import { secureStorage } from '@/utils/secureStorage'
import { networkOptimizer } from '@/utils/networkOptimization'
import { inputValidator } from '@/utils/inputValidation'
import { xssProtection } from '@/utils/xssProtection'

import type { 
  ApiResponse, 
  LoginRequest, 
  LoginResponse, 
  UserInfo,
  SendMessageRequest,
  MessageResponse,
  GetMessagesRequest,
  PaginatedResponse,
  MarkMessageReadRequest,
  FriendListResponse,
  SearchFriendsRequest,
  Friend,
  ConversationListResponse,
  ErrorResponse
} from '@/types'

// 重试配置
interface RetryConfig {
  maxRetries: number
  retryDelay: number
  retryCondition?: (error: AxiosError) => boolean
}

class ApiService {
  private userInstance: AxiosInstance
  private messageInstance: AxiosInstance
  private refreshTokenPromise: Promise<string> | null = null

  constructor() {
    // 用户服务实例
    this.userInstance = axios.create({
      baseURL: config.api.userBaseURL,
      timeout: config.api.timeout,
      headers: {
        'Content-Type': 'application/json',
      },
    })

    // 消息服务实例
    this.messageInstance = axios.create({
      baseURL: config.api.messageBaseURL,
      timeout: config.api.timeout,
      headers: {
        'Content-Type': 'application/json',
      },
    })

    this.setupInterceptors()
    this.setupNetworkOptimization()
  }

  private setupNetworkOptimization() {
    // 设置网络优化器的清理定时器
    setInterval(() => {
      networkOptimizer.cleanupCache()
    }, 60000) // 每分钟清理一次缓存
  }

  private setupInterceptors() {
    const setupInstanceInterceptors = (instance: AxiosInstance) => {
      // 请求拦截器
      instance.interceptors.request.use(
        (config) => {
          // 优先使用安全存储的Token
          const secureToken = secureStorage.getAccessToken()
          const fallbackToken = userStorage.getToken()
          const token = secureToken || fallbackToken
          
          if (token) {
            config.headers.Authorization = `Bearer ${token}`
          }
          
          // 添加安全头
          config.headers['X-Requested-With'] = 'XMLHttpRequest'
          config.headers['X-Content-Type-Options'] = 'nosniff'
          
          return config
        },
        (error) => Promise.reject(error)
      )

      // 响应拦截器
      instance.interceptors.response.use(
        (response) => response.data,
        async (error: AxiosError) => {
          const originalRequest = error.config as AxiosRequestConfig & { _retry?: boolean }

          // 处理401错误 - Token过期
          if (error.response?.status === 401 && !originalRequest._retry) {
            originalRequest._retry = true

            try {
              // 尝试刷新Token
              const newToken = await this.handleTokenRefresh()
              if (newToken && originalRequest.headers) {
                originalRequest.headers.Authorization = `Bearer ${newToken}`
                return instance(originalRequest)
              }
            } catch (refreshError) {
              // 刷新失败，跳转到登录页
              this.handleAuthFailure()
              return Promise.reject(refreshError)
            }
          }

          // 处理其他错误
          return Promise.reject(this.handleApiError(error))
        }
      )
    }

    setupInstanceInterceptors(this.userInstance)
    setupInstanceInterceptors(this.messageInstance)
  }

  private async handleTokenRefresh(): Promise<string> {
    // 防止并发刷新Token
    if (this.refreshTokenPromise) {
      return this.refreshTokenPromise
    }

    this.refreshTokenPromise = this.performTokenRefresh()
    
    try {
      const newToken = await this.refreshTokenPromise
      return newToken
    } finally {
      this.refreshTokenPromise = null
    }
  }

  private async performTokenRefresh(): Promise<string> {
    const refreshToken = userStorage.getRefreshToken()
    if (!refreshToken) {
      throw new Error('No refresh token available')
    }

    try {
      const response = await this.userInstance.post('/api/auth/refresh', {
        refreshToken
      }) as ApiResponse<{ token: string; refreshToken: string }>

      if (response.success && response.data) {
        const { token, refreshToken: newRefreshToken } = response.data
        userStorage.setToken(token)
        userStorage.setRefreshToken(newRefreshToken)
        return token
      } else {
        throw new Error('Token refresh failed')
      }
    } catch (error) {
      userStorage.clearUserData()
      throw error
    }
  }

  private handleAuthFailure() {
    userStorage.clearUserData()
    // 触发全局认证失败事件
    window.dispatchEvent(new CustomEvent('auth:failure'))
  }

  private handleApiError(error: AxiosError): ErrorResponse {
    const response = error.response
    const errorResponse: ErrorResponse = {
      error: error.name || 'ApiError',
      message: error.message || 'An unknown error occurred',
      code: response?.status || 0,
      timestamp: new Date()
    }

    if (response?.data) {
      const data = response.data as any
      errorResponse.message = data.message || data.error || errorResponse.message
      errorResponse.details = data.details
    }

    return errorResponse
  }

  // 重试机制
  private async withRetry<T>(
    operation: () => Promise<T>,
    retryConfig: RetryConfig = { maxRetries: 3, retryDelay: 1000 }
  ): Promise<T> {
    let lastError: Error
    
    for (let attempt = 0; attempt <= retryConfig.maxRetries; attempt++) {
      try {
        return await operation()
      } catch (error) {
        lastError = error as Error
        
        // 检查是否应该重试
        if (attempt === retryConfig.maxRetries) {
          break
        }

        if (retryConfig.retryCondition && !retryConfig.retryCondition(error as AxiosError)) {
          break
        }

        // 等待后重试
        await new Promise(resolve => setTimeout(resolve, retryConfig.retryDelay * Math.pow(2, attempt)))
      }
    }

    throw lastError!
  }

  // ============================================================================
  // 认证相关API
  // ============================================================================

  /**
   * 用户登录
   */
  async login(request: LoginRequest): Promise<LoginResponse> {
    // 验证登录请求数据
    const validation = inputValidator.validateLoginForm(request)
    if (!validation.isValid) {
      throw new Error(`Invalid login data: ${validation.errors.join(', ')}`)
    }

    // 使用清理后的数据
    const sanitizedRequest = validation.sanitizedValue as LoginRequest

    const response = await this.withRetry(() => 
      this.userInstance.post('/api/auth/login', sanitizedRequest)
    ) as ApiResponse<LoginResponse>

    if (!response.success || !response.data) {
      throw new Error(response.message || 'Login failed')
    }

    // 保存认证信息到安全存储
    const { token, refreshToken, user, expiresIn } = response.data
    
    // 优先使用安全存储
    const tokenSaved = secureStorage.setTokenInfo({
      token,
      refreshToken,
      expiresAt: Date.now() + (expiresIn * 1000),
      userId: user.id
    })

    // 如果安全存储失败，回退到普通存储
    if (!tokenSaved) {
      console.warn('Secure storage failed, falling back to regular storage')
      userStorage.setToken(token)
      userStorage.setRefreshToken(refreshToken)
    }
    
    userStorage.setUserInfo(user)

    return response.data
  }

  /**
   * 用户注册
   */
  async register(request: { username: string; password: string; nickname: string; email: string; phone?: string }): Promise<UserInfo> {
    // 验证注册请求数据
    const validation = inputValidator.validateRegisterForm({
      username: request.username,
      password: request.password,
      email: request.email,
      phone: request.phone
    })
    if (!validation.isValid) {
      throw new Error(`Invalid register data: ${validation.errors.join(', ')}`)
    }

    // 构建后端期望的请求格式
    const backendRequest = {
      username: request.username,
      password: request.password,
      nickname: request.nickname,
      email: request.email,
      phone: request.phone || null
    }

    const response = await this.withRetry(() => 
      this.userInstance.post('/api/auth/register', backendRequest)
    ) as ApiResponse<UserInfo>

    if (!response.success || !response.data) {
      throw new Error(response.message || 'Registration failed')
    }

    return response.data
  }

  /**
   * 用户登出
   */
  async logout(): Promise<void> {
    try {
      await this.userInstance.post('/api/auth/logout')
    } catch (error) {
      // 即使登出请求失败，也要清除本地存储
      console.warn('Logout request failed:', error)
    } finally {
      userStorage.clearUserData()
    }
  }

  /**
   * 刷新Token
   */
  async refreshToken(): Promise<string> {
    return this.handleTokenRefresh()
  }

  /**
   * 获取当前用户信息
   */
  async getCurrentUser(): Promise<UserInfo> {
    const response = await this.userInstance.get('/api/auth/me') as ApiResponse<UserInfo>
    
    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to get user info')
    }

    return response.data
  }

  /**
   * 搜索用户
   */
  async searchUsers(keyword: string): Promise<UserInfo[]> {
    const params = new URLSearchParams()
    params.append('keyword', keyword)

    const response = await this.userInstance.get(`/api/users/search?${params.toString()}`) as any

    // 适配后端的实际响应格式
    // 后端返回的是 { code: 200, message: "Success", data: [...], timestamp: ... } 格式
    if (response.code !== 200 || !response.data) {
      throw new Error(response.message || 'Failed to search users')
    }

    return response.data || []
  }

  // ============================================================================
  // 消息相关API
  // ============================================================================

  /**
   * 发送消息
   */
  async sendMessage(request: SendMessageRequest): Promise<MessageResponse> {
    // 验证消息内容
    const messageTypeForValidation = request.messageType === 'SYSTEM' ? 'TEXT' : request.messageType
    const contentValidation = inputValidator.validateMessageContent(
      request.content.text || request.content.imageUrl || request.content.fileUrl || '',
      messageTypeForValidation as 'TEXT' | 'IMAGE' | 'FILE' | 'VOICE'
    )
    
    if (!contentValidation.isValid) {
      throw new Error(`Invalid message content: ${contentValidation.errors.join(', ')}`)
    }

    // 创建安全的请求对象
    const sanitizedRequest: SendMessageRequest = {
      ...request,
      content: {
        ...request.content
      }
    }

    // 对文本消息进行XSS防护
    if (request.messageType === 'TEXT' && request.content.text) {
      sanitizedRequest.content.text = xssProtection.sanitizeTextMessage(request.content.text)
    }

    // 验证文件名（如果有）
    if (request.content.fileName) {
      const fileNameValidation = inputValidator.validateFileName(request.content.fileName)
      if (!fileNameValidation.isValid) {
        throw new Error(`Invalid file name: ${fileNameValidation.errors.join(', ')}`)
      }
      sanitizedRequest.content.fileName = fileNameValidation.sanitizedValue
    }

    const response = await this.withRetry(() =>
      this.messageInstance.post('/api/messages', sanitizedRequest),
      {
        maxRetries: 2,
        retryDelay: 500,
        retryCondition: (error) => {
          // 只对网络错误和5xx错误重试
          return !error.response || error.response.status >= 500
        }
      }
    ) as ApiResponse<MessageResponse>

    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to send message')
    }

    return response.data
  }

  /**
   * 获取会话消息列表
   */
  async getConversationMessages(request: GetMessagesRequest): Promise<PaginatedResponse<MessageResponse>> {
    const params = new URLSearchParams()
    if (request.page) params.append('page', request.page.toString())
    if (request.pageSize) params.append('pageSize', request.pageSize.toString())
    if (request.beforeMessageId) params.append('beforeMessageId', request.beforeMessageId)
    if (request.afterMessageId) params.append('afterMessageId', request.afterMessageId)

    const response = await this.withRetry(() =>
      this.messageInstance.get(`/api/conversations/${request.conversationId}/messages?${params.toString()}`)
    ) as ApiResponse<PaginatedResponse<MessageResponse>>

    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to get messages')
    }

    return response.data
  }

  /**
   * 标记消息为已读
   */
  async markMessageAsRead(request: MarkMessageReadRequest): Promise<void> {
    const response = await this.messageInstance.put(
      `/api/messages/${request.messageId}/read`,
      { conversationId: request.conversationId }
    ) as ApiResponse<void>

    if (!response.success) {
      throw new Error(response.message || 'Failed to mark message as read')
    }
  }

  /**
   * 批量标记消息为已读
   */
  async markMessagesAsRead(conversationId: string, messageIds: string[]): Promise<void> {
    const response = await this.messageInstance.put(
      `/api/conversations/${conversationId}/messages/read`,
      { messageIds }
    ) as ApiResponse<void>

    if (!response.success) {
      throw new Error(response.message || 'Failed to mark messages as read')
    }
  }

  /**
   * 获取会话列表
   */
  async getConversations(): Promise<ConversationListResponse> {
    const response = await this.withRetry(() =>
      this.messageInstance.get('/api/conversations')
    ) as ApiResponse<ConversationListResponse>

    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to get conversations')
    }

    return response.data
  }

  // ============================================================================
  // 好友相关API
  // ============================================================================

  /**
   * 获取好友列表
   */
  async getFriendList(): Promise<FriendListResponse> {
    const response = await this.withRetry(() =>
      this.userInstance.get('/api/friends')
    ) as ApiResponse<FriendListResponse>

    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to get friend list')
    }

    return response.data
  }

  /**
   * 搜索好友
   */
  async searchFriends(request: SearchFriendsRequest): Promise<PaginatedResponse<Friend>> {
    const params = new URLSearchParams()
    params.append('keyword', request.keyword)
    if (request.page) params.append('page', request.page.toString())
    if (request.pageSize) params.append('pageSize', request.pageSize.toString())

    const response = await this.withRetry(() =>
      this.userInstance.get(
        `/api/friends/search?${params.toString()}`
      )
    ) as ApiResponse<PaginatedResponse<Friend>>

    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to search friends')
    }

    return response.data
  }

  /**
   * 获取好友在线状态
   */
  async getFriendStatus(userId: number): Promise<{ status: string; lastActiveTime: Date }> {
    const response = await this.userInstance.get(
      `/api/friends/${userId}/status`
    ) as ApiResponse<{ status: string; lastActiveTime: Date }>

    if (!response.success || !response.data) {
      throw new Error(response.message || 'Failed to get friend status')
    }

    return response.data
  }

  /**
   * 添加好友
   */
  async addFriend(userId: number): Promise<void> {
    const response = await this.userInstance.post('/api/friends', { userId }) as ApiResponse<void>

    if (!response.success) {
      throw new Error(response.message || 'Failed to add friend')
    }
  }

  /**
   * 删除好友
   */
  async removeFriend(userId: number): Promise<void> {
    const response = await this.userInstance.delete(`/api/friends/${userId}`) as ApiResponse<void>

    if (!response.success) {
      throw new Error(response.message || 'Failed to remove friend')
    }
  }

  // ============================================================================
  // 好友请求相关API
  // ============================================================================

  /**
   * 发送好友请求
   */
  async sendFriendRequest(toUserId: number, message?: string): Promise<void> {
    const currentUser = userStorage.getUserInfo() as UserInfo | null
    if (!currentUser) {
      throw new Error('User not logged in')
    }

    const request = {
      fromUserId: currentUser.id,
      toUserId,
      message: message || ''
    }

    const response = await this.userInstance.post('/api/friend-requests', request) as any

    // 后端直接返回 FriendRequestResponse 对象，如果有 id 字段说明成功
    if (!response.id) {
      throw new Error('Failed to send friend request')
    }
  }

  /**
   * 接受好友请求
   */
  async acceptFriendRequest(requestId: number): Promise<void> {
    const currentUser = userStorage.getUserInfo() as UserInfo | null
    if (!currentUser) {
      throw new Error('User not logged in')
    }

    const request = {
      userId: currentUser.id
    }

    const response = await this.userInstance.post(`/api/friend-requests/${requestId}/accept`, request)

    // 后端返回空响应，只要没有抛出异常就说明成功
    // 如果有错误，axios 会抛出异常
  }

  /**
   * 拒绝好友请求
   */
  async rejectFriendRequest(requestId: number, reason?: string): Promise<void> {
    const currentUser = userStorage.getUserInfo() as UserInfo | null
    if (!currentUser) {
      throw new Error('User not logged in')
    }

    const request = {
      userId: currentUser.id,
      reason: reason || ''
    }

    const response = await this.userInstance.post(`/api/friend-requests/${requestId}/reject`, request)

    // 后端返回空响应，只要没有抛出异常就说明成功
  }

  /**
   * 取消好友请求
   */
  async cancelFriendRequest(requestId: number): Promise<void> {
    const currentUser = userStorage.getUserInfo() as UserInfo | null
    if (!currentUser) {
      throw new Error('User not logged in')
    }

    const request = {
      userId: currentUser.id
    }

    const response = await this.userInstance.post(`/api/friend-requests/${requestId}/cancel`, request)

    // 后端返回空响应，只要没有抛出异常就说明成功
  }

  /**
   * 获取收到的好友请求
   */
  async getReceivedFriendRequests(page: number = 0, pageSize: number = 20): Promise<any> {
    const currentUser = userStorage.getUserInfo() as UserInfo | null
    if (!currentUser) {
      throw new Error('User not logged in')
    }

    const params = new URLSearchParams()
    params.append('userId', currentUser.id.toString())
    params.append('page', page.toString())
    params.append('size', pageSize.toString())

    const response = await this.userInstance.get(`/api/friend-requests/received?${params.toString()}`) as any

    // 后端直接返回 PageResponse 对象
    if (!response.content) {
      throw new Error('Failed to get received friend requests')
    }

    return response
  }

  /**
   * 获取发送的好友请求
   */
  async getSentFriendRequests(page: number = 0, pageSize: number = 20): Promise<any> {
    const currentUser = userStorage.getUserInfo() as UserInfo | null
    if (!currentUser) {
      throw new Error('User not logged in')
    }

    const params = new URLSearchParams()
    params.append('userId', currentUser.id.toString())
    params.append('page', page.toString())
    params.append('size', pageSize.toString())

    const response = await this.userInstance.get(`/api/friend-requests/sent?${params.toString()}`) as any

    // 后端直接返回 PageResponse 对象
    if (!response.content) {
      throw new Error('Failed to get sent friend requests')
    }

    return response
  }

  /**
   * 获取待处理请求数量
   */
  async getPendingRequestCount(): Promise<number> {
    const currentUser = userStorage.getUserInfo() as UserInfo | null
    if (!currentUser) {
      throw new Error('User not logged in')
    }

    const params = new URLSearchParams()
    params.append('userId', currentUser.id.toString())

    const response = await this.userInstance.get(`/api/friend-requests/pending-count?${params.toString()}`) as any

    // 后端直接返回 PendingCountResponse 对象 {"count": number}
    if (response.count !== undefined) {
      return response.count
    }

    throw new Error('Failed to get pending request count')
  }

  /**
   * 检查是否可以发送好友请求
   */
  async canSendFriendRequest(toUserId: number): Promise<boolean> {
    const currentUser = userStorage.getUserInfo() as UserInfo | null
    if (!currentUser) {
      throw new Error('User not logged in')
    }

    const params = new URLSearchParams()
    params.append('fromUserId', currentUser.id.toString())
    params.append('toUserId', toUserId.toString())

    const response = await this.userInstance.get(`/api/friend-requests/can-send?${params.toString()}`) as any

    // 适配后端的直接响应格式 {"canSend": true}
    if (response.canSend !== undefined) {
      return response.canSend
    }

    throw new Error('Failed to check if can send friend request')
  }

  // ============================================================================
  // 通用HTTP方法
  // ============================================================================

  // 用户服务相关 API
  async userGet<T>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.userInstance.get(url, config)
  }

  async userPost<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.userInstance.post(url, data, config)
  }

  async userPut<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.userInstance.put(url, data, config)
  }

  async userDelete<T>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.userInstance.delete(url, config)
  }

  // 消息服务相关 API
  async messageGet<T>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.messageInstance.get(url, config)
  }

  async messagePost<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.messageInstance.post(url, data, config)
  }

  async messagePut<T>(url: string, data?: unknown, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.messageInstance.put(url, data, config)
  }

  async messageDelete<T>(url: string, config?: AxiosRequestConfig): Promise<ApiResponse<T>> {
    return this.messageInstance.delete(url, config)
  }
}

export const apiService = new ApiService()